#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//int main()
//{
	//第8讲：VS实⽤调试技巧：

	//***************************
	//2. 什么是调试（debug）？
	//***************************
	//当我们发现程序中存在的问题的时候，那下⼀步就是找到问题，并修复问题。
	//这个找问题的过程叫称为调试，英⽂叫debug（消灭bug）的意思。
	//调试⼀个程序，⾸先是承认出现了问题，然后通过各种⼿段去定位问题的位置，可能是逐过程的调
	//试，也可能是隔离和屏蔽代码的⽅式，找到问题所的位置，然后确定错误产⽣的原因，再修复代码，
	//重新测试。



	//***************************
	//3. Debug 和 Release
	//***************************
	//Debug 通常称为调试版本，它包含调试信息，并且不作任何优化，便于程序员调试程序
	//Release 称为发布版本，它往往是进⾏了各种优化，使得程序在代码⼤⼩和运⾏速度上都是最优的



	//***************************
	//4. VS调试快捷键
	//***************************
	//4.1 环境准备
	//应该把VS上设置为Debug


	//4.2 调试快捷键
	//调试最常使⽤的⼏个快捷键：
	//F9：创建断点和取消断点
	//断点的作⽤是可以在程序的任意位置设置断点，打上断点就可以使得程序执⾏到想要的位置暂停执
	//⾏，接下来我们就可以使⽤F10，F11这些快捷键，观察代码的执⾏细节
	//条件断点:满足某个条件就在这里断
	//for (int i = 0; i < 10; i++)
	//{
	//	printf("hehe\n");//在这里设置断点和下一个for循环里设置断点，按f5不会跳到下一个断点执行。原因是代码执行是按照逻辑的，第一个for循环还没有走完，代码向上走，向下执行时仍然遇到这个断点.
	//}
	//for (int i = 0; i < 10; i++)
	//{
	//	printf("haha\n");
	//}

	//F10：逐过程，通常⽤来处理⼀个过程，⼀个过程可以是⼀次函数调⽤，或者是⼀条语句。
	//但是F10无法看函数内容

	//F11：逐语句，就是每次都执⾏⼀条语句，但是这个快捷键可以使我们的执⾏逻辑进⼊函数内部。在函
	//数调⽤的地⽅，想进⼊函数观察细节，必须使⽤F11，如果使⽤F10，直接完成函数调⽤。

	//CTRL + F5：开始执行不调试，如果你想让程序直接运行起来而不调试就可以直接使用。


	//***************************
	//5. 监视和内存观察
	//***************************
	//在调试的过程中我们，如果要观察代码执⾏过程中，上下⽂环境中的变量的值，有哪些⽅法呢？
	//5.1 监视
	//开始调试后，在菜单栏中【调试】->【窗⼝】->【监视】，打开任意⼀个监视窗⼝，输⼊想要观察的对象就⾏

	//5.2 内存
	//如果监视窗⼝看的不够仔细，也是可以观察变量在内存中的存储情况，还是在【调试】->【窗⼝】->【内存】



	//6. 调试举例1
	//int n = 0;
	//int i = 0;
	//int temp = 1;
	//int sum = 0;
	//for (n = 1; n <= 3; n++)
	//{
	//	for (i = 1; i <= n; i++)
	//	{
	//		temp *= i;//求1!+2!+3! 正确结果应	该是9，但是程序运行发现结果是15，调试后发现temp的值需要在每一次循环的时候进行初始化
	//	}
	//	sum += temp;
	//}
	//printf("%d", sum);

	

	//7. 调试举例2
	//在VS2022、X86、Debug 的环境下，编译器不做任何优化的话，下⾯代码执⾏的结果是啥？
	//int i = 0;
	//int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//for (i = 0; i <= 12; i++)
	//{
	//	arr[i] = 0;
	//	printf("hehe\n");
	//}
	//注意体会调试的重要性
	//1.栈区内存的使⽤习惯是从⾼地址向低地址使⽤的，所以变量i的地址是较⼤的。arr数组的地址整体是⼩于i的地址
	//2. 数组在内存中的存放是：随着下标的增⻓，地址是由低到⾼变化的
	//所以arr[12]的地址就有可能与i的地址一样

	//注意：栈区的默认的使⽤习惯是先使⽤⾼地址，再使⽤低地址的空间，但是这个具体还是要编译器的实现
	//⽐如：在VS上切换到X64，这个使⽤的顺序就是相反的，在Release版本的程序中，这个使⽤的顺序也是相反的。


	//数组传参时的调试技巧:
	//在数组传参，调试进⼊函数，如何在监视窗⼝观察数组的内容： 数组名,n 的形式
	//void test1(int arr[10]);
	//void test2(int arr2[3][5]);
	//int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//test1(arr);
	//int arr2[3][5] =
	//{
	//	{2,3,4,5,6},
	//	{2,5,6,7,8},
	//	{1,1,1,1}
	//};
	//test2(arr2);//例如查看这个二维数组里的内容就是:arr2,3 一般形式就是:arr,n (这里的n指的就是数组的行数)
//	return 0;
//}
//void test1(int arr[10])//走入函数体里的时候需要用arr,10来查看数组里所有内容
//{
//	;
//}
//void test2(int arr2[3][5])
//{
//	;
//}

//第9讲：函数递归：
//1. 递归是什么？
//递归其实是⼀种解决问题的⽅法，在C语⾔中，递归就是函数⾃⼰调⽤⾃⼰。
//int main()
//{
//	printf("hehe\n");
//	main();//每一次函数调用都会占有一块空间，即在栈区上申请空间 名字叫:函数栈帧空间（运行时堆栈）
//	return 0;//这个代码算是递归，但是是错误示范导致栈溢出(Stack overflow)所以递归必须是有条件的
//}




